# @FileName  : conf.py
# @Time      : 2025/3/6 04:46
# @Author    : LuZhaoHui
# @Software  : PyCharm

from configparser import ConfigParser
from tool.vars import *
from tool.file import *
from tool.str import *


class MyParser(ConfigParser):
    # Inherit from built-in class: ConfigParser
    def optionxform(self, option_str):
        # Rewrite without lower()
        return option_str


JSON_DICT = {
    '时间': '',
    '模型': '',
    '对话': '',
    '图片': '',
    '信息': [],
    '标题': '',
    '属性': [],
    '耗时': 0,
    '结果': ''
}

JSON_TITLE = ['表格', '秘级']

JSON_ATTR = {
    '表格': 1,
    '秘密': 2,
    '机密': 2,
}

SHIJUNAME = {
    'rhcg': '入户存根',
    'wfwg': '违法违规',
    'lmph': '楼门牌号',
    'whk': '无户口',
    'zqcg': '准迁存根',
    'zhcl': '综合材料',
    'xczsh': '审核',
    'xczsp': '审批',
    'xczsq': '入户申请',
    'spcl': '审批材料',
    'spclsh': '审核',
    'spclsp': '审批',
    'spclsq': '入户申请',
    'qstksp': '审批',
    'qstksq': '入户申请',
    'whksp': '审批',
    'whksq': '无户申请'
}

SHIJUTYPE = {
    'rhcg': 'Rhcg',
    'wfwg': 'Wfwg',
    'lmph': 'Lmph',
    'whk': 'Whk',
    'zqcg': 'Zqcg',
    'zhcl': 'Zhcl',
    'xczsh': 'XczSH',
    'xczsp': 'XczSP',
    'xczsq': 'XczSQ',
    'spcl': 'Spcl',
    'spclsh': 'SpclSH',
    'spclsp': 'SpclSP',
    'spclsq': 'SpclSQ',
    'qstksp': 'QstkSP',
    'qstksq': 'QstkSQ',
    'whksp': 'WhkSP',
    'whksq': 'WhkSQ',
}

SHIJU_DICT = {
    '入户通知': 'rhcg',
    '违法违规': 'wfwg',
    '楼门牌号': 'lmph',
    '无户口': 'whk',
    '户口准迁': 'zqcg',
    '准予迁入': 'zqcg',
    '综合材料': 'zhcl',
    '材料审核': 'xczsh',
    '住房审核': 'xczsh',
    '投资审核': 'xczsh',
    '户口审批': 'xczsp',
    '投靠审批': 'xczsp',
    '投靠入户申请': 'xczsq',
    '投靠申请': 'xczsq',
    '户口申请': 'xczsq',
    '审核': 'spclsh',
    '审批': 'spclsp',
    '入户申请': 'spclsq',
    '人户申请': 'spclsq',
    '申请表': 'spclsq'
}

SHIJU_KEY = {
    'rhcg': ['姓名', '性别', '生日', '身份', '批件', '派出所', '人数', '地址', '来文', '收文',
             '签收', '经办', '签发'],
    'zqcg': ['姓名', '身份', '字号', '住址', '职业', '登记', '发往单位', '迁入地址', '原因', '签发', '批准',
             '承办人', '备注'],
    'wfwg': ['编号', '姓名'],
    'lmph': ['编号', '姓名'],
    'whk': ['编号', '姓名'],
    'zhcl': ['编号', '姓名'],
    'xczsh': ['姓名', '性别', '年龄', '住址', '地址', '农户类型', '投靠', '意见'],
    'xczsp': ['姓名', '性别', '出生', '身份','地址', '分字号', '编号', '户别', '派出所名称', '迁移原因', '意见', '随迁'],
    'xczsq': ['姓名', '性别', '出生', '身份', '民族', '籍贯', '现户口地址', '户口所在', '入户地址', '派出所', '审批',
              '分字号', '文化', '户别', '来京', '结婚', '迁移原因', '入户理由', '随迁'],
    'spcl': ['标题','姓名', '批件号', '文字'],
    'spclsh': ['姓名', '性别', '年龄', '住址', '农户类型', '投靠', '意见'],
    'spclsp': ['姓名', '入户地址', '分字号', '编号', '户别', '派出所名称', '迁移原因', '意见', '批示'],
    'spclsq': ['姓名', '性别', '出生', '身份', '民族', '籍贯', '现户口地址', '户口所在', '入户地址', '派出所', '审批',
               '分字号', '文化', '户别', '来京', '结婚', '迁移原因', '入户理由', '随迁人员'],
    'qstksp': ['姓名', '入户地址', '分字号', '编号', '户别', '派出所', '迁移原因', '入户时间', '文字'],
    'qstksq': ['姓名', '性别', '出生', '身份', '民族', '现户口地址', '入户地址', '派出所', '审批',
               '分字号', '编号', '户别', '来京', '结婚', '入户理由', '文字', '随迁人员'],
    'whksp': ['姓名', '入户地址', '分字号', '编号', '户别', '派出所', '迁移原因', '入户时间', '文字'],
    'whksq': ['姓名', '性别', '出生', '身份', '民族', '现户口地址', '入户地址', '派出所', '审批',
              '分字号', '编号', '户别', '来京', '结婚', '入户理由', '文字', '随迁人员'],
}

YANQING_KEY = {
    'hkdj1':['住址','人数','个人信息'],
    'hkdj0':['标题','户主姓名','户主关系'],
    'hkdj2': ['标题', '个人信息', '户主信息'],
    'hkdj3': ['公社', '人数', '个人信息'],
    'hkdj9': ['标题', '人数', '个人信息']
}

PERSON_DICT = {
    '身份证': ['*姓名', '性别', '出生', '民族', '*住址', '签发', '有效期', '*编号'],
    '户口信息': ['*单位', '*名称', '*姓名', '性别', '出生', '民族', '*住址'],
    # '登记卡':['*姓名','性别','民族','*出生时间','*婚否','出生地','籍贯','*现住地'],
    # '登记卡':['*个人信息','*户主信息'],
    '个人登记卡片': ['-总人数', '*个人信息', '*户主信息'],
    '个人信息表': [
        '*姓名', '*别名', '性别', '出生日期', '民族', '*身份证', '*婚姻状况', '*文化程度', '籍贯',
        '单位职业', '迁入本市', '迁入本址', '现住址', '*登记时间'],
    '户口登记簿': ['标题内容', '*现住址', '*总人数', '*个人信息'],
    '公共户口证明书': ['标题', '*正式住址', '*总人数', '*个人信息'],
    '常住人口登记表': ['*总人数', '*个人信息'],
}

JSONERR = ''


def changeJsonLine(line, result):
    line_list = result.split('\n')
    data = ''
    for row, ls in enumerate(line_list):
        if row > 0:
            data += '\n'
        data += ls
        if (row + 1) == line:
            if ls[-1:] == ',':
                data = data[:-1] + ':\"\",'
            else:
                data += ':\"\"'
    return data


def annlyseJsonErr(result):
    global JSONERR
    key = "':' expected after dictionary key (<string>, line"
    pos = JSONERR.find(key)
    line = -1
    if pos >= 0:
        s = JSONERR[pos + len(key):]
        pos = s.find(')')
        if pos > 0:
            ls = s[:pos]
            try:
                line = int(ls)
            except:
                line = -1
    return line

def resultAddJson(result):
    data = result.lstrip('```json').rstrip('```').lstrip('\n').rstrip('\n')
    return '```json\n' + data + '\n```'

def resultToJson(result):
    err = False
    global JSONERR
    try:
        data = result.lstrip('```json').rstrip('```')
        if data.find('title') >= 0:
            data = data.replace('title', '标题')
        if data.find('secret_level') >= 0:
            data = data.replace('secret_level', '秘级')
        if data.find('is_table') >= 0:
            data = data.replace('is_table', '表格')
        if data.find('true') >= 0:
            data = data.replace('true', 'True')
        if data.find('false') >= 0:
            data = data.replace('false', 'False')
        if data.find('\"是\"') >= 0:
            data = data.replace('\"是\"', 'True')
        if data.find('\"否\"') >= 0:
            if data.find('\"结婚时间\"') < 0:
                data = data.replace('\"否\"', 'False')
        ret = eval(data)
        JSONERR = ''
    except Exception as e:
        save_error_log('result json err [%s]' % str(e))
        JSONERR = str(e)
        err = True
        ret = result
    return ret, err


def setJson(jsondata):
    if jsondata is not None:
        for k, v in JSON_DICT.items():
            if k not in jsondata.keys():
                jsondata[k] = v
    return jsondata


def getJsonAttr(attr):
    t = False
    ms = ''
    for k in attr:
        if k not in JSON_ATTR.keys():
            continue
        v = JSON_ATTR[k]
        if v == 1:
            t = True
        if v == 2:
            ms = k
    return t, ms


def getJsonTitle(jsondata):
    title = ''
    if '标题' in jsondata.keys():
        p = jsondata['标题'].find('|')
        title = jsondata['标题'][:p] if p >= 0 else jsondata['标题']
        # 优化
        title = title.replace('\n', '').replace(' ', '').replace('“', '').replace('”', '')
        title = title.replace('（', '(').replace('）', ')')
        title = title.replace('人户', '入户')
    return title

def getJsonHead(jsondata):
    head = {}
    for k, v in jsondata.items():
        if '抬头' in k:
            if type(v) == dict:
                head = v.copy()
                break
    return head

def checkJson(jsonData):
    # 核查json
    setJson(jsonData)
    isUpdate = False
    if jsonData['标题'] == '' or len(jsonData['属性']) == 0:
        try:
            result = resultToJson(jsonData['结果'])
            if type(result) == dict:
                if '标题' in result.keys():
                    jsonData['标题'] = str(result['标题']).replace('|', '')
                    isUpdate = True
                if len(jsonData['属性']) == 0:
                    if '是否表格' in result.keys():
                        if result['是否表格']:
                            jsonData['属性'].append('表格')
                            isUpdate = True
                    if '秘级' in result.keys() and result['秘级'] != '':
                        jsonData['属性'].append(result['秘级'])
                        isUpdate = True
        except:
            isUpdate = False
    return isUpdate


def isJson(jsondata):
    if jsondata is None:
        return False
    for key in JSON_DICT.keys():
        if key not in jsondata.keys():
            if key == '信息':
                continue
            return False
    return True


def isTitleJson(jsondata):
    if jsondata is None:
        return False
    for key in JSON_TITLE:
        for k in jsondata.keys():
            if key in str(k):
                return True
    # if len(jsondata.keys()) < 3:
    #     return True
    return False

def isResultHead(hs, filter):
    if hs == '' or not filter:
        return True
    hs_list = hs.split('|')
    for hk in hs_list:
        if not isListInStr(hk,hs_list):
            return False
    return True

def isFullTextTitle(ts, filter):
    for s in filter.split('|'):
        if s == '':
            if ts == '':
                return False
            continue
        if ts.find(s) >=0:
            return False
    return True

def isResultTitle(ts, filter, max_len=64):
    if len(ts) > max_len:
        return False
    f_list = []
    pos1 = filter.find('[')
    pos2 = filter.find(']')
    if pos1 >= 0 and pos1 < pos2:
        f1 = filter[:pos1]
        f2 = filter[pos2 + 1:]
        fl = filter[pos1 + 1:pos2].split(',')
        for f in fl:
            f_list.append(f1 + f + f2)
    else:
        f_list.append(filter)
    for f in f_list:
        if f[0] == '-' and f[-1] == '-':
            if f[1:-1] in ts:
                return True
        if f[0] == '-':
            l = len(f[1:])
            if f[-l:] == ts[-l:]:
                return True
        if f[-1] == '-':
            l = len(filter[:-1])
            if f[:l] == ts[:l]:
                return True
        if f == ts:
            return True
    return False


class WebConf:
    # 配置
    varConf = {
        'Title': '大模型在线测试',
        'ImagePath': '/home/image',
        'ResultPath': '/home/result',
        'IsStart': False,
    }
    varModel = {
        'ModelPath': '/home/models',
        'ModelName': 'Qwen2.5-VL-7B',
        'SystemPrompt': '图片信息',
    }
    varPara = {
        'stream': False,
        'max_tokens': 1024,  # 最大TOKEN数,控制生成的内容的长度;
        'temperature': 0.7,  # 温度;0.0-1.5..;控制输出文本的随机性;
        'top_p': 0.7,  # 核采样;0.0-1.0；控制模型选择的概率范围;
        'top_k': 40,  # 前K采样;1-~;限制模型每次选择时考虑的候选词数，防止低概率词出现
        'presence_penalty': 0.0,  # 控制生成文本中是否包含新话题;-2.0-2.0;
        'frequency_penalty': 0.0,  # 频率惩罚,减少重复;-2.0-2.0;
        'n': 1,  # 回复数量
    }
    varWeb = {
        'IsWebServer': True,  # 启动WEB服务
        'WebHost': '',  # 可访问IP
        'WebPort': 8099,  # 访问端口
        'WebChatUrl': '/aiChat',  # 访问URL
        'WebModelUrl': '/model',  # 查询模型URL
    }
    varMysql = {
        'IsMysql': False,
        'MysqlHost': '127.0.0.1',
        'MysqlPort': 3306,
        'MysqlUser': 'root',
        'MysqlPass': 'root',
        'MysqlDatabase': 'LLM',
    }
    vars = {
        'CONF': varConf,
        'MODEL': varModel,
        'PARA': varPara,
        'WEB': varWeb,
        'MYSQL': varMysql
    }

    def __init__(self, file):
        self.config = MyParser()
        self.name = file
        self.read()

    def get(self, section, key):
        return self.config.get(section, key)

    def read(self):
        self.config.read(self.name, 'utf-8')
        # 取配置
        for key, vs in self.vars.items():
            # print("%s:%s" % (key, vars))
            for k, v in vs.items():
                # print("%s:%s" % (key, k))
                s = self.get(key, k)
                if isinstance(vs[k], bool):
                    vs[k] = bool(eval(s))
                elif isinstance(vs[k], int):
                    vs[k] = int(s)
                elif isinstance(vs[k], float):
                    vs[k] = float(s)
                elif isinstance(vs[k], list):
                    vs[k] = s.split(',')
                else:
                    vs[k] = s

    def write(self, section, key, value):
        self.config.set(section, key, str(value))
        with open(self.name, 'w', encoding='utf-8') as f:
            self.config.write(f)


class ChatConf:
    # 配置
    varConf = {
        'Title': '大模型在线测试',
        'WindowMax': False,
    }
    varData = {
        'IsLocal': True,
        'DataHost': '127.0.0.1',
        'DataPort': 22,
        'DataUser': 'dashen',
        'DataPass': 'dashen',
        'DataHome': '/home/dashen/data/',
        'DataHomeImage': 'image',
        'DataHomeResult': 'result',
        'DataPath': '',
        'CurDir': '',
        'DirDeep': 1,
        'DirNest': False,
        'FilterMode': 0,
        'FilterMsg': '',
        'ResultPath': '',
    }
    varModel = {
        'ModelName': '',
        'SystemPrompt': '',
        'PromptListNums': 20,
        'PromptList0': ['获取图片的标题和全部信息', ],
        'PromptList1': ['获取图片的标题和全部信息', ],
        'PromptList2': ['获取图片的标题和全部信息', ],
        'PromptList3': ['获取图片的标题和全部信息', ],
        'PromptList4': ['获取图片的标题和全部信息', ],
        # 'ChatCurPrompt': '',
        # 'ChatMultiReason': False,
        # 'ChatMultiNums': 9,
        # 'ChatMultiResult': [],
        # 'ChatMultiText': [],
        # 'ChatMultiPrompt': '',
        # 'ChatMultiResult1': [],
        # 'ChatMultiText1': [],
        # 'ChatMultiPrompt1': '',
        # 'ChatMultiResult2': [],
        # 'ChatMultiText2': [],
        # 'ChatMultiPrompt2': '',
    }
    varChat = {
        'ChatTypeNums': 20,
        'ChatTypeList': [],
        'ChatTypeExtList': [],
        'ChatAllText': False,
        'ChatFilter': False,
        'ChatContinue': False,
        'ChatFilterRegex': False,
        'ChatLockType': False,
        'ChatDefineKey': [],
        'ChatTitleMaxLen': 64
    }
    varPrompt = {
    }
    varReason = {
        'WebUrl': 'http：//',
        'WebChatUrl': '/aiChat',
        'WebModelUrl': '/model',
        'WebIndex': 0,
        'WebHost': [],
        'WebPort': 8000,
        'TimeOut': 120,
        'ImageRed': False,
        'ImageSelf': False,
        'ImageZoom': 1.0,
        'ImageWidth': 0,
        'ImageHeight': 0,
    }
    varPdf = {
        'IsPdf': False,
        'PdfHost': '127.0.0.1',
        'PdfPort': 22,
        'PdfUser': 'dashen',
        'PdfPass': 'dashen',
        'PdfPath': '/home/dashen/data',
    }
    vars = {
        'CONF': varConf,
        'DATA': varData,
        'MODEL': varModel,
        'CHAT': varChat,
        'REASON': varReason,
        'PDF': varPdf
    }

    def __init__(self, file):
        self.config = MyParser()
        self.name = CONF_PATH + '/' + file
        self.varChatTypeList = []
        self.read()

    def get(self, section, key):
        return self.config.get(section, key)

    def setChat(self):
        # chat
        self.varChatTypeList.clear()
        if len(self.varChat['ChatTypeList']) != 4:
            self.varChat['ChatTypeList'] = ['会话', '会话', '默认1', '默认2']
        self.varChatTypeList.append(self.varChat['ChatTypeList'][0])
        for pos in range(self.varChat['ChatTypeNums']):
            self.varChatTypeList.append('%s%d' % (self.varChat['ChatTypeList'][1], pos + 1))
        self.varChatTypeList.append(self.varChat['ChatTypeList'][2])
        self.varChatTypeList.append(self.varChat['ChatTypeList'][3])
        self.varPrompt.clear()
        if len(self.varChat['ChatDefineKey']) != 4:
            self.varChat['ChatDefineKey'] = ['ChatTitle', 'ChatPrompt', 'ChatDefaultPrompt1', 'ChatDefaultPrompt2']
        self.varPrompt[self.varChat['ChatDefineKey'][1]] = ''
        self.varPrompt[self.varChat['ChatDefineKey'][2]] = ''
        self.varPrompt[self.varChat['ChatDefineKey'][3]] = ''
        for pos in range(self.varChat['ChatTypeNums']):
            self.varPrompt['%s%d' % (self.varChat['ChatDefineKey'][0], pos + 1)] = ''
            self.varPrompt['ChatEnable%d' % (pos + 1)] = False
            self.varPrompt['%s%d' % (self.varChat['ChatDefineKey'][1], pos + 1)] = ''
        self.readPrompt()

    def readPrompt(self):
        self.config.read(self.name, 'utf-8')
        key = 'PROMPT'
        for k, v in self.varPrompt.items():
            try:
                s = self.get(key, k)
            except:
                self.write(key, k, v)
                continue
            if isinstance(self.varPrompt[k], bool):
                self.varPrompt[k] = bool(eval(s))
            else:
                self.varPrompt[k] = s

    def read(self):
        self.config.read(self.name, 'utf-8')
        for key, vs in self.vars.items():
            # print("%s:%s" % (key, vars))
            for k, v in vs.items():
                # print("%s:%s" % (key, k))
                try:
                    s = self.get(key, k)
                except:
                    self.write(key, k, v)
                    continue
                if isinstance(vs[k], bool):
                    vs[k] = bool(eval(s))
                elif isinstance(vs[k], int):
                    vs[k] = int(s)
                elif isinstance(vs[k], float):
                    vs[k] = float(s)
                elif isinstance(vs[k], list):
                    vs[k] = s.split('|')
                else:
                    vs[k] = s
        self.setChat()

    def write(self, section, key, value):
        self.config.set(section, key, str(value))
        with open(self.name, 'w', encoding='utf-8') as f:
            self.config.write(f)

    def writeSet(self, section, key, value):
        self.config.set(section, key, str(value))

    def writeSave(self):
        with open(self.name, 'w', encoding='utf-8') as f:
            self.config.write(f)


class ResultConf:
    # 配置
    varConf = {
        'Title': '大模型在线测试',
        'WindowMax': False
    }
    varData = {
        'DataHost': '127.0.0.1',
        'DataPort': 22,
        'DataUser': 'dashen',
        'DataPass': 'dashen',
        'DataHome': '/home/dashen/data/',
        'DataHomeImage': 'image',
        'DataHomeResult': 'result',
        'CurDir': '',
        'DirDeep': 1,
        'DirNest': False,
        'ImageSelf': True,
        'ResultKeys': '',
        'ResultOnly': False,
        'ResultCheck': False,
        'ResultAllText': False,
        'ResultModify': False,
        'WriteMinDelay': 20,
        'WriteDelay': 200,
        'WriteImage': False,
        'ChatTitleNums': 50,
        'CharTitlePos': [0, 0],
        'ChatTitleMaxLen': 64
    }

    varPrompt = {}

    varMysql = {
        'MysqlHost': '127.0.0.1',
        'MysqlPort': 22,
        'MysqlUser': 'root',
        'MysqlPass': 'root',
        'MysqlDbIndex': 0,
        'MysqlDB': ['llm'],
    }
    vars = {
        'CONF': varConf,
        'DATA': varData,
        'MYSQL': varMysql
    }

    def __init__(self, file):
        self.config = MyParser()
        self.name = CONF_PATH + '/' + file
        self.varChatTitleList = []
        self.read()

    def get(self, section, key):
        return self.config.get(section, key)

    def setPrompt(self):
        self.varPrompt.clear()
        for pos in range(self.varData['ChatTitleNums']):
            self.varPrompt['ChatTitle%d' % (pos + 1)] = ''
        self.readPrompt()
        for v in self.varPrompt.values():
            if len(v):
                self.varChatTitleList.append(v)

    def readPrompt(self):
        self.config.read(self.name, 'utf-8')
        key = 'PROMPT'
        for k, v in self.varPrompt.items():
            try:
                s = self.get(key, k)
            except:
                self.write(key, k, v)
                continue
            self.varPrompt[k] = s

    def read(self):
        self.config.read(self.name, 'utf-8')
        # 取配置
        for key, vs in self.vars.items():
            # print("%s:%s" % (key, vars))
            for k, v in vs.items():
                # print("%s:%s" % (key, k))
                try:
                    s = self.get(key, k)
                except:
                    self.write(key, k, v)
                    continue
                if isinstance(vs[k], bool):
                    vs[k] = bool(eval(s))
                elif isinstance(vs[k], int):
                    vs[k] = int(s)
                elif isinstance(vs[k], float):
                    vs[k] = float(s)
                elif isinstance(vs[k], list):
                    sl = s.split(',')
                    if type(v[0]) == int:
                        vs[k] = [int(pos) for pos in sl]
                    else:
                        vs[k] = sl
                else:
                    vs[k] = s
        self.setPrompt()

    def write(self, section, key, value):
        self.config.set(section, key, str(value))
        with open(self.name, 'w', encoding='utf-8') as f:
            self.config.write(f)
